package utils

import (
	"archive/zip"
	"encoding/csv"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"os"
	"path"
	"strings"
)

// GetSize get the file size
func GetSize(f multipart.File) (int, error) {
	content, err := ioutil.ReadAll(f)

	return len(content), err
}

// GetExt get the file ext
func GetExt(fileName string) string {
	return path.Ext(fileName)
}

// CheckNotExist check if the file exists
func CheckNotExist(src string) bool {
	_, err := os.Stat(src)

	return os.IsNotExist(err)
}

// CheckPermission check if the file has permission
func CheckPermission(src string) bool {
	_, err := os.Stat(src)

	return os.IsPermission(err)
}

// IsNotExistMkDir create a directory if it does not exist
func IsNotExistMkDir(src string) error {
	if notExist := CheckNotExist(src); notExist {
		if err := MkDir(src); err != nil {
			return err
		}
	}

	return nil
}

// MkDir create a directory
func MkDir(src string) error {
	err := os.MkdirAll(src, os.ModePerm)
	if err != nil {
		return err
	}

	return nil
}

// Open a file according to a specific mode
func Open(name string, flag int, perm os.FileMode) (*os.File, error) {
	f, err := os.OpenFile(name, flag, perm)
	if err != nil {
		return nil, err
	}

	return f, nil
}

// MustOpen maximize trying to open the file
func MustOpen(fileName, filePath string) (*os.File, error) {
	dir, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("os.Getwd err: %v", err)
	}

	src := dir + "/" + filePath
	perm := CheckPermission(src)
	if perm {
		return nil, fmt.Errorf("file.CheckPermission Permission denied src: %s", src)
	}

	err = IsNotExistMkDir(src)
	if err != nil {
		return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
	}

	f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		return nil, fmt.Errorf("Fail to OpenFile :%v", err)
	}

	return f, nil
}

func Zip(zipPath string, zipName string, files []string) error {
	err := os.MkdirAll(zipPath, os.ModePerm)
	if err != nil {
		return err
	}
	fz, err := os.Create(zipPath + "/" + zipName)
	if err != nil {
		return err
	}
	zw := zip.NewWriter(fz)
	defer zw.Close()

	for _, fileName := range files {
		fr, err := os.Open(fileName)
		if err != nil {
			return err
		}

		// 写入文件的头信息
		var w io.Writer
		w, err = zw.Create(fileName)

		if err != nil {
			return err
		}

		// 写入文件内容
		_, err = io.Copy(w, fr)
		if err != nil {
			return err
		}
	}
	return zw.Flush()
}

// 判断是否是有效的文件扩展名
func IsValidFileExt(filename string, validExtList []string) bool {
	//fileExt := strings.ToLower(path.Ext(filename))
	for _, s := range validExtList {
		if strings.HasSuffix(filename, s) {
			return true
		}
	}
	return false
}

func WriteToCsv(filePath string, fileName string, header []string, records [][]string) error {
	err := os.MkdirAll(filePath, os.ModePerm)
	if err != nil {
		return err
	}
	// 创建一个文件
	csvFile, err := os.Create(filePath + "/" + fileName)
	if err != nil {
		return err
	}
	defer csvFile.Close()

	// 初始化一个csv writer，并通过这个 writer 写入数据到csv文件
	writer := csv.NewWriter(csvFile)
	// 将writer缓冲中的数据都推送到csv文件，完成数据写入到csv文件
	defer writer.Flush()

	_, err = csvFile.WriteString("\xEF\xBB\xBF") // 写入UTF-8 BOM，避免使用Microsoft Excel打开乱码
	if err != nil {
		return err
	}

	// 写标题行
	err = writer.Write(header)
	if err != nil {
		return err
	}

	// 写数据行
	for _, line := range records {
		// 将切片类型行数据写入 csv 文件
		err := writer.Write(line)
		if err != nil {
			return err
		}
	}
	return nil
}
